6.1

使用 VTIME 设置驱动程序超时

play_again5.c

#include <stdio.h>
#include <termios.h>
/* #include <fcntl.h> */
#include <string.h>

#define ASK "Do you want another transaction"
#define TRIES 3
#define SLEEPTIME 2
#define BEEP putchar('\a')

int get_response(char *, int);
void tty_mode(int);
void set_crmode();
void set_cr_noecho_mode();
/* void set_nodelay_mode(); */
char get_ok_char();

int main()
{
    int response;
    tty_mode(0);        /* save tty mode */
    set_cr_noecho_mode();  /* set -icanon, -echo */
    /* set_nodelay_mode(); */
    response = get_response(ASK, TRIES);
    tty_mode(1);        /* restore tty mode */
    return response;
}

int get_response(char *question, int maxtries)
{
    int input;
    printf("%s (y/n)?", question);
    while(1){
        sleep(SLEEPTIME);
        input = tolower(get_ok_char());
        if (input == 'y')
            return 0;

        if (input == 'n')
            return 1;

        if (maxtries-- == 0)
            return 2;
        BEEP;
    }
}

char get_ok_char()
{
    int c;
    while ((c = getchar()) != EOF && strchr("yYnN", c) == NULL)
        ;
    return c;
}

void set_cr_noecho_mode()
{
    struct termios ttystate;
    tcgetattr(0, &ttystate);
    ttystate.c_lflag     &= ~ICANON;  /* no buffering */
    ttystate.c_lflag      &= ~ECHO;    /* no echo either */
    ttystate.c_cc[VTIME] = 20;  /* set timeout */
    ttystate.c_cc[VMIN] = 0;
    tcsetattr(0, TCSANOW, &ttystate);
}

/* void set_nodelay_mode() */
/* { */
/*     int termflags; */
/*     termflags = fcntl(0, F_GETFL); */
/*     termflags |= O_NDELAY; */
/*     fcntl(0, F_SETFL, termflags); */
/* } */

void tty_mode(int how)
{
    static struct termios original_mode;
    /* static int original_flags; */
    if (how == 0){
        /* tcgetattr(0, &original_mode); */
        original_flags = fcntl(0, F_GETFL);
    }
    else{
        /* tcsetattr(0, TCSANOW, &original_mode); */
        fcntl(0, F_SETFL, original_flags);
    }
}

6.5

#include <stdio.h>
#include <ctype.h>
#include <termios.h>
#include <strings.h>
#include <signal.h>

void set_noecho_nodelay_mode();
void tty_mode(int);
void cc_handle(int);


int main()
{
    int c;
    tty_mode(0);
    signal(SIGINT, cc_handle);
    signal(SIGQUIT, SIG_IGN);
    set_noecho_nodelay_mode();
    while ((c = getchar()) != EOF){
        if (c == 'Q'){
            tty_mode(1);
            return 0;
        }

        if (c == 'z')
            c = 'a';
        else if (islower(c))
            c++;
        putchar(c);
    }
    return 0;
}

void cc_handle(int signum)
{
    tty_mode(1);
    exit(1);
}

void set_noecho_nodelay_mode()
{
    struct termios tty_set;
    tcgetattr(0, &tty_set);
    tty_set.c_lflag &= ~ICANON;
    tty_set.c_lflag &= ~ECHO;
    tty_set.c_cc[VTIME] = 20;
    tty_set.c_cc[VMIN] = 0;
    tcsetattr(0, TCSANOW, &tty_set);
}

void tty_mode(int mode)
    /*
     * mode == 0 : store mode
     * mode != 0 : restore mode
     */
{
    static struct termios tbuf;
    if (mode == 0){
        tcgetattr(0, &tbuf);
    }else{
        tcsetattr(0, TCSANOW, &tbuf);
    }
}

6.6

#include <stdio.h>
#include <ctype.h>
#include <termios.h>
#include <strings.h>
#include <signal.h>

void set_noecho_nodelay_mode();
void tty_mode(int);
void cc_handle(int);
void handle_char(char);


int main()
{
    int c;
    tty_mode(0);
    signal(SIGINT, cc_handle);
    signal(SIGQUIT, SIG_IGN);
    set_noecho_nodelay_mode();
    while ((c = getchar()) != EOF){
        /* printf("%d\n", c); */
        handle_char(c);
    }
    return 0;
}

void kill_char()
{
    putchar('\b');
    putchar(' ');
    putchar('\b');
}

void handle_char(char c)
{
    static char buf[BUFSIZ];
    static int i = 0;
    struct termios tb;
    tcgetattr(0, &tb);
    if (c == tb.c_cc[VERASE]){
        kill_char();
        i--;
    }else if (c == tb.c_cc[VWERASE]){
        int j = 0;
        for (; i >= 0; i--, j++){
            if (buf[i] == ' ' && j != 0){
                break;
            }else{
                kill_char();
            }
        }
    }else if (c == tb.c_cc[VKILL]){
        for (; i >= 0; i--){
            kill_char();
        }
    }else{
        putchar(c);
        buf[i] = c;
        i++;
    }
}

void cc_handle(int signum)
{
    tty_mode(1);
    exit(1);
}

void set_noecho_nodelay_mode()
{
    struct termios tty_set;
    tcgetattr(0, &tty_set);
    tty_set.c_lflag &= ~ICANON;
    tty_set.c_lflag &= ~ECHO;
    tty_set.c_cc[VMIN] = 1;
    tcsetattr(0, TCSANOW, &tty_set);
}

void tty_mode(int mode)
    /*
     * mode == 0 : store mode
     * mode != 0 : restore mode
     */
{
    static struct termios tbuf;
    if (mode == 0){
        tcgetattr(0, &tbuf);
    }else{
        tcsetattr(0, TCSANOW, &tbuf);
    }
}